﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;

namespace LinguaHDL
{
    public partial class Form2_ShowFSM : Form
    {
        public Form2_ShowFSM()
        {
            InitializeComponent();
            Instance = this;
        }
        public static Form2_ShowFSM Instance;

        

        private void Form2_ShowFSM_Load(object sender, EventArgs e)
        {

           
        }

        public string openFile(string fileFilter, out string fileExtensionType)
        {
            OpenFileDialog openFile = new OpenFileDialog();
            // openFile.InitialDirectory = "F://";
            openFile.Filter = fileFilter;

            // openFile.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
            openFile.Multiselect = false;
            fileExtensionType = null;
            if (openFile.ShowDialog() == DialogResult.Cancel) return "err";
            var filePath = openFile.FileName;

            string fileType = System.IO.Path.GetExtension(filePath);
            if (string.IsNullOrEmpty(fileType)) return "err";
            FileInfo fileinfo = new FileInfo(openFile.SafeFileName);
            //在此处添加后续操作
            fileExtensionType = fileType;
            return filePath;

        }

        //将目标文件按行装载在list中
        //输入：目标文件全路径
        //输出：包含文件所有内容的list<string>
        public List<string> loadFile(string filePath)
        {
            List<string> list_str = new List<string>();
            FileStream fs = new FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read);

            //StreamReader sr = new StreamReader(fs, Encoding.UTF8);
            StreamReader sr = new StreamReader(fs, Encoding.Default);

            //记录每次读取的一行记录
            string strLine = "";
            while ((strLine = sr.ReadLine()) != null)
            {
                list_str.Add(strLine);
            }
            sr.Close();
            fs.Close();
            return list_str;

        }

        List<string> VerilogFSMState_localparam = new List<string>();

        public void LoadFSMBlock()
        {
            string fileFilter = "Verilog Flile(*.v)|*.v";//|VHDL Flile(*.vhd)|*.vhd";
            string fileType;
            string filePath = openFile(fileFilter, out fileType);
            if (filePath == "err") return;
            List<string> list_str = new List<string>();
            list_str = loadFile(filePath);
            //把状态机定义添加到VerilogFSMState_localparam
            foreach (string ver_line in list_str)
            {
                string ver_line_regu;
                string[] verLineReguArry;
                if (ver_line.Contains("localparam"))
                {
                    //把制表符替换成空格，然后依据空格分割，最后获得状态机各状态名称
                    ver_line_regu = ver_line.Replace("\t", " ");
                    verLineReguArry = ver_line_regu.Split(' ');
                    VerilogFSMState_localparam.Add(verLineReguArry[1]);
                }
            }
            DataTable FSMSearchDataTable = CreateFSMSearchDataTable();
            DataRow dr;





            for (int lineNumber = 1; lineNumber <= list_str.Count; lineNumber++)
            {
                foreach (string fsmName in VerilogFSMState_localparam)
                {
                    //列表索引从0开始，但是行号从1开始
                    string lineContent = list_str[lineNumber - 1];
                    string lineContentPure = lineContent.Replace("\t", " ");
                    lineContentPure = lineContentPure.Replace(" ", "");
                    //寻找case入口
                    if (lineContentPure.Contains(fsmName + ':'))
                    {
                        dr = FSMSearchDataTable.NewRow();
                        dr["FSMName"] = fsmName;
                        dr["lineNumber"] = lineNumber;
                        FSMSearchDataTable.Rows.Add(dr);



                    }

                }

            }
            //针对最后一个状态添加一个结束行号项
            int lastRowNum = FSMSearchDataTable.Rows.Count - 1;
            int start_lineNumH = (int)FSMSearchDataTable.Rows[lastRowNum]["lineNumber"];
            int beginCount = 0;
            for (int lineNum = start_lineNumH;
                lineNum < list_str.Count;
                lineNum++)
            {
                string lineContent = list_str[lineNum];
                lineContent = lineContent.Replace("\t", " ");

                if (lineContent.Contains("begin"))
                {
                    beginCount += 1;

                }
                else if (lineContent.Contains("end") &&
                         !lineContent.Contains("endcase") &&
                         !lineContent.Contains("endmodule")
                    )
                {
                    beginCount -= 1;
                    if (beginCount == 0)
                    {
                        dr = FSMSearchDataTable.NewRow();
                        dr["FSMName"] = "last";
                        dr["lineNumber"] = lineNum;
                        FSMSearchDataTable.Rows.Add(dr);
                        break;
                    }

                }
                // Form2_ShowFSM.Instance.richTextBox1.Text += lineContent+" " +beginCount.ToString() + "\n";

            }
            //获取每个状态的可能后继状态
            Dictionary<string, List<string>> stateNextState_dic = new Dictionary<string, List<string>>();
            //遍历行号表
            for (int i = 0; i < FSMSearchDataTable.Rows.Count - 1; i++) //
            {
                List<string> nextStateArry = new List<string>();

                //遍历一个state case所在的行
                int start_lineNum = (int)FSMSearchDataTable.Rows[i]["lineNumber"];
                int end_lineNum = (int)FSMSearchDataTable.Rows[i + 1]["lineNumber"];

                for (int lineNum = start_lineNum + 1;
                    lineNum < end_lineNum;
                    lineNum++)
                {
                    //在这些行中寻找state名称
                    foreach (string fsmName in VerilogFSMState_localparam)
                    {
                        if (list_str[lineNum - 1].Contains(fsmName))
                        {
                            nextStateArry.Add(fsmName);
                            Console.WriteLine(fsmName);

                        }
                    }



                }

                if (nextStateArry.Count > 0)
                {
                    string key = FSMSearchDataTable.Rows[i]["FSMName"].ToString();

                    stateNextState_dic.Add(key, nextStateArry);
                }

            }//遍历行号表结束

            //开始绘制状态图
            //Form2_ShowFSM.Instance.placeStateCells(stateNextState_dic);
            foreach (string key in stateNextState_dic.Keys)
            {
                TreeNode node = new TreeNode();

                node.Text = key;

                List<string> stateList = stateNextState_dic[key];
                for (int i = 0; i < stateList.Count; i++)
                {
                    TreeNode childNode = new TreeNode();
                    childNode.Text = stateList[i];
                    node.Nodes.Add(childNode);
                }
                Form2_ShowFSM.Instance.treeView1.Nodes.Add(node);



            }





        }

        public DataTable CreateFSMSearchDataTable()
        {
            DataTable FSMSearchDataTable = new DataTable();

            DataColumn FSMName = new DataColumn("FSMName");
            DataColumn lineNumber = new DataColumn("lineNumber");

            FSMName.DataType = Type.GetType("System.String");
            lineNumber.DataType = Type.GetType("System.Int32");

            FSMSearchDataTable.Columns.Add(FSMName);
            FSMSearchDataTable.Columns.Add(lineNumber);

            return FSMSearchDataTable;
        }

        private void button1_showfsm_Click(object sender, EventArgs e)
        {
            LoadFSMBlock();
        }

        
        
        

    }

    
}
